/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cocma;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import schedulingScheme.Helper;
import schedulingScheme.POI;
import schedulingScheme.SensorNode;

/**
 *
 * @author Andrzej
 */
public class CocmaImproved extends Cocma{

    public CocmaImproved(List<SensorNode> nodes, List<POI> pois) {
        super(nodes, pois);
    }
    /**
 * wake-up scheme - new version
 * @param s sensor that died
 * @return set of nodes that shoul be added to network to replace died sensor
 *
 */

    @Override
    public List<SensorNode> replaceDiedSensor(SensorNode s) {

        int index = nodes.indexOf(s);
        BitSet b = R.coverageOfSensor(index);
        BitSet zeros = new BitSet(b.length());


        BitSet uncoveredPOIs;
        BitSet tmp1;
        BitSet coveredPOIsWithoutDiedSensor = new BitSet(b.length());

        for (int i=0; i< nodes.size();i++){
            if (nodes.get(i).isOn())
                coveredPOIsWithoutDiedSensor.or(R.coverageOfSensor(i));
        }
        tmp1  = ((BitSet)coveredPOIsWithoutDiedSensor.clone());
        tmp1.or(b);
        tmp1.xor(coveredPOIsWithoutDiedSensor);
        uncoveredPOIs = tmp1;
        assert(b.cardinality() >= uncoveredPOIs.cardinality()):"" + b.cardinality() + " < " + uncoveredPOIs.cardinality();

        List<SensorNode> neighbors = new ArrayList<SensorNode>();
        System.out.println(uncoveredPOIs);
        for (int i = 0; i < nodes.size(); i++) {
            if (nodes.get(i).isOn() == false && nodes.get(i).getBattery() > 0) {
                BitSet tmp = (BitSet) uncoveredPOIs.clone();
                tmp.and(R.coverageOfSensor(i));
                if (tmp.cardinality() > 0) {
                    neighbors.add(nodes.get(i));
                }
            }
        }
        List<List<SensorNode>> subsets = Helper.getAllSubsets(neighbors);
        List<SensorNode> bestSubset = Collections.EMPTY_LIST;
        double bestValue = Double.NEGATIVE_INFINITY;
        Chromosome baseChromosome = new Chromosome(nodes.size());
        for (int i=0;i < nodes.size(); i++){
            baseChromosome.setAllele(i, nodes.get(i).isOn());
        }
        for (List<SensorNode> subset : subsets){
            if (subset.size() == 0)
                continue;
            Chromosome tmp = (Chromosome) baseChromosome.clone();
            for (SensorNode sn: subset){
                tmp.setAllele(nodes.indexOf(sn), true);
            }
            double value = fv.fitnessValue(tmp);
            if (value > bestValue){
                bestSubset = subset;
                bestValue = value;
            }

        }
        for (SensorNode sensor: bestSubset){
            sensor.setOn(true);
        }
        return bestSubset;
    }

}
